﻿#ifndef JZNODE_PROJECT_H_
#define JZNODE_PROJECT_H_

#include <QSet>
#include <QMap>
#include "JZNode.h"
#include "JZNodeObject.h"
#include "JZProjectItem.h"
#include "JZParamItem.h"
#include "JZScriptItem.h"
#include "JZClassItem.h"
#include "JZScriptFile.h"
#include "JZScriptEnvironment.h"
#include "JZRegExpHelp.h"

enum BreakPointChange
{
    BreakPoint_add,
    BreakPoint_remove,
};

//BreakPoint
class BreakPoint
{
public: 
    enum Type{
        none,
        nodeEnter,
        print,  
    };

    BreakPoint();

    Type type;
    QString scriptItemPath;
    int nodeId;
};
void operator<<(QDataStream &s, const BreakPoint &param);
void operator>>(QDataStream &s, BreakPoint &param);

//JZProjectTempGuard
class JZProjectTempGuard
{
public:
    enum AfterOpertaor
    {
        RemoveItem,
        TakeItem,
    };

    JZProjectTempGuard(JZProject *project, JZProjectItem *item, AfterOpertaor op, const QString &className = QString());
    JZProjectTempGuard(JZProject* project, QList<JZProjectItem*> items, AfterOpertaor op, const QString &className = QString());
    ~JZProjectTempGuard();

protected:
    JZProject *m_project;
    QList<JZProjectItem*> m_items;
    AfterOpertaor m_after;
};

//JZProject
class JZProject : public QObject
{
    Q_OBJECT

public:
    JZProject();
    ~JZProject();

    bool isNull() const;
    void clear();
    void copyTo(JZProject *other) const;

    JZScriptEnvironment *environment();
    const JZScriptEnvironment *environment() const;    

    QString absoluteFilePath(QString path) const;
    
    bool open(QString filepath);
    void close();
    bool save();      //只保存工程自身，不保存项目文件
    bool saveAs(QString filepath);

    void registType();
    void unregistType();
    
    void addTmp(JZProjectItem* item);
    void setTmpClass(JZProjectItem* item, QString className);
    void removeTmp(JZProjectItem *item);
    void takeTmp(JZProjectItem *item);
    bool isTmp(JZProjectItem *item);
    JZScriptClassItem* tmpClassItem(JZProjectItem* item); //根据tmp名称

    bool isFile(JZProjectItem *item);

    void saveTransaction();
    void saveCommit();

    void saveCache();  //保存 breakpoint 之类的设置信息
    void loadCache();

    QString error() const;

    QString name() const;
    QString path() const;

    void setFilePath(QString path);
    QString filePath() const;

    JZScriptFile *mainFile();
    QString mainFilePath();

    JZScriptItem *mainFunction(); 
    QString mainFunctionPath();
    
    JZParamItem *globalDefine();
    void addGlobalVariable(const QString &name,QString dataType,const QString &value = QString());
    void addGlobalVariable(const QString &name,int dataType,const QString &value = QString());
    const JZParamDefine *globalVariable(QString name);
    QStringList globalVariableList();

    JZProjectItem *root();

    JZProjectItem *addFile(QString path);
    void removeFile(QString path);        

    JZScriptClassItem *getClass(QString class_name);
    QStringList classList();

    bool addItem(QString path, JZProjectItem *item);
    void removeItem(QString path);
    JZProjectItem *getItem(QString path);
    QList<JZProjectItem*> itemList(QString path, int type);
    bool saveItem(JZProjectItem *item);
    bool saveItems(QList<JZProjectItem*> item);
    void saveItemMeta(QString old_item_path, JZProjectItem* item);
    bool saveAllItem();
    bool renameItem(JZProjectItem *item, QString name);    

    JZScriptClassItem *getItemClass(JZProjectItem *item);    
    JZProjectItem *getItemFile(JZProjectItem *item);
    JZScriptFile *getScriptFile(JZProjectItem *item);
    
    const JZFunctionDefine *function(QString name);
    JZScriptItem *functionItem(QString function_name);
    QStringList functionList();

    void addBreakPoint(const BreakPoint &pt);
    void removeBreakPoint(QString file,int id);
    bool hasBreakPoint(QString file,int id);
    BreakPoint breakPoint(QString file, int id);
    QList<BreakPoint> breakPoints();

    void onItemChanged(JZProjectItem *item);

signals:
    void sigDefineChanged();
    void sigItemChanged(JZProjectItem *item);
    void sigBreakPointChanged(BreakPointChange reason,QString file, int id);
    void sigScriptNodeChanged(JZScriptItem *file, int nodeId,const QByteArray &buffer);    

protected:
    Q_DISABLE_COPY(JZProject)

    QList<JZProjectItem *> paramDefineList();

    QString domain(JZProjectItem *item);        
    QString dir(const QString &filepath);    
    int indexOfBreakPoint(QString file,int id);
    void loadFinish();
            
    QString m_filepath;
    JZProjectItemRoot m_root;
    JZProjectItemRoot m_tmp;  
    QMap<JZProjectItem*, QString> m_tmpClass;

    QMap<JZProjectItem*, QList<BreakPoint>> m_breakPoints;
    
    QString m_error;
    bool m_blockRegist;
    bool m_isSaveCache;
    QList<JZProjectItem*> m_saveCache;  //为了避免每次save写文件
    JZScriptEnvironment m_env;
};

void JZProjectInit();

#endif
